package ca.uwaterloo.call;

import java.util.Date;
import java.util.HashSet;
import java.util.Set;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Intent;
import android.content.SharedPreferences;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.TextView;

public class MainActivity extends Activity {
	LinearLayout show;
	SP spmanager;
	Button toContact, toCallCard,toClear;
	final static int GET_CONTACT = 0;
	final static int GET_CALLCARD = 1;
	Date now;
	boolean defaultcard;
	TextView Warning;
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		
		show = (LinearLayout) findViewById(R.id.label);
		show.setOrientation(LinearLayout.VERTICAL);
		
		spmanager = new SP();
	
	//  for test use
	//	spmanager.Clear();
		
	/*	for test use
	    spmanager.Clear();
	    spmanager.putin(SP.Default_Pin, "2995479389");
		spmanager.putin("6214804364"+SP._PRE, "18669138555,,1,");
		spmanager.putin("2995479389"+SP._PRE, "18669138555,,1,");
		Set<String> a = new HashSet<String>();
		a.add("6214804364");
		a.add("2995479389");
		spmanager.putin(SP.Pin_Set, a);
		spmanager.putin(SP.Total_CallCard_Number, 2);
		
		a = new HashSet<String>();
		a.add("home");
		a.add("mom");
		a.add("grandfather");
		a.add("father");
		spmanager.putin(SP.Name_Set, a);
		spmanager.putin("home"+SP._PHONE, "011862885405809");
		spmanager.putin("mom"+SP._PHONE, "0118615198039993");
		spmanager.putin("grandfather"+SP._PHONE, "011862866582379");
		spmanager.putin("father"+SP._PHONE, "0118613678096118");
		spmanager.putin(SP.Total_Contact_Number, 4); 
		*/
		
		SPtoV(); //copy date from shared preferences to the program variables.
		Warning = new TextView(getApplicationContext());
		Warning.setText("no available call card");
		
		if (CallCard_inuse == null) {
			show.addView(Warning);
		}
		
		toContact = (Button) findViewById(R.id.button1);
		toContact.setOnClickListener(new View.OnClickListener() {
			
			@Override
			public void onClick(View v) {
				// go to CantactRegister
				Intent goContact = new Intent(MainActivity.this, ContactRegister.class);
				startActivityForResult(goContact,GET_CONTACT);
			}
		});
		
		toCallCard = (Button) findViewById(R.id.button2);
		toCallCard.setOnClickListener(new View.OnClickListener() {
			
			@Override
			public void onClick(View v) {
				// go to CallCardRegister
				Intent goCallCard = new Intent(MainActivity.this, CallCardRegister.class);
				try {
					goCallCard.putExtra("PRE", CallCard_inuse.getPre());
					goCallCard.putExtra("PIN", CallCard_inuse.getPin());
				} catch(Exception e) {}
				
				startActivityForResult(goCallCard,GET_CALLCARD);
			}
		});
		
	/*	toClear = (Button) findViewById(R.id.button3);
		toClear.setOnClickListener(new View.OnClickListener() {
			
			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				spmanager.Clear();
			}
		}); */
		
		now = new Date();
		
		for (int i=0; i<Contact_total ; i++) {
			Contact_all[i].present();
		}
	}
	
	@Override
	public void onActivityResult (int requestCode, int resultCode, Intent data) {
		//when a Contact information is sent back from the ContactRegister
		if (requestCode == GET_CONTACT && resultCode == RESULT_OK) {
			if (data.hasExtra("New_Name") && data.hasExtra("New_Phone")) {
				String name = data.getExtras().getString("New_Name");
				String phone = data.getExtras().getString("New_Phone");
				int al = Integer.parseInt(data.getExtras().getString("New_Alert"));
				Contact_all[Contact_total] = new Contact(name, phone,al);
				Contact_all[Contact_total].present();
				Contact_total++;
			}
		}
		
		//when a Call Card information is sent back from the CallCardRegister
		if (requestCode == GET_CALLCARD && resultCode == RESULT_OK) {
			if (data.hasExtra("PRE")) {
				String pre = data.getExtras().getString("PRE");
				String pin = data.getExtras().getString("PHO");
				CallCard_all[CallCard_total] = new CallCard(pre, pin);
				CallCard_inuse = CallCard_all[CallCard_total];
				CallCard_total++;
				if (CallCard_inuse != null) show.removeView(Warning);
			}
		}
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.activity_main, menu);
		return true;
	}
	
	@Override
	protected void onDestroy() {
		spmanager.Clear();
		spmanager.StoreInfo();
		super.onDestroy();		
	}
	
	public class SP {
		//The class SP manage the shared preferences. Followed is how it stores data: 
		/* key                                value
		 * "Name_Set"						  the string set of all contact names(Set<String>)
		 * A+"_PHONE"						  the phone number of A(String)
		 * A+"_ALERT"						  the alert day of A(int), 0 if alert is not set.
		 * A+"_YEAR"						  the year of your last calling A(int)
		 * A+"_MONTH"						  the month of your last calling A(int)
		 * A+"_DAY"							  the day of your last calling A(int)
		 * "Total_Contact_number"			  the number of contacts(int)
		 * "Pin_set"						  the set of all call cards' pin number(Set<String>)
		 * A+"_PRE"							  the prefix(the number you need to dial before dialing PIN) of A(String)
		*/
		SharedPreferences.Editor editor;
		SharedPreferences settings;
		
		final static String Name_Set = "Name_Set";
		final static String Pin_Set = "Pin_set";
		final static String Total_CallCard_Number = "Total_CallCard_Number";
		final static String Total_Contact_Number ="Total_Contact_Number";
		final static String _PRE = "_PRE";
		final static String _PHONE = "_PHONE";
		final static String _ALERT = "_ALERT";
		final static String _YEAR = "_YEAR";
		final static String _MONTH = "_MONTH";
		final static String _DAY = "_DAY";
		final static String Default_Pin = "Default_Pin";
		
		public SP() {
			settings = getSharedPreferences("MylongCall",0);
		}
		
		public void remove(String key) {
			//remove the value with corresponding key in the shared preferences.
			editor = settings.edit();
			editor.remove(key);
			editor.commit();
		}
		
		public void putin(String key, String value) {
			//put in the key-value pair into shared preferences.
			editor = settings.edit();
			editor.putString(key,value);
			editor.commit();
		}
		
		public void putin(String key, int value) {
			editor = settings.edit();
			editor.putInt(key, value);
			editor.commit();
		}
		
		@SuppressLint("NewApi")
		public void putin(String key, Set<String> value) {
			editor = settings.edit();
			editor.putStringSet(key, value);
			editor.commit();
		}
			
		public int getCallCardnumber() {
			//return the number of call cards, if the key-value pair doesn't exist in 
			//shared preferences, return 0.
			return settings.getInt(Total_CallCard_Number,0);
		}
	
		public int getContactnumber() {
			//return the number of contacts, if the key-value pair doesn't exist in 
			//shared preferences, return 0.
			return settings.getInt(Total_Contact_Number, 0);
		}
		
		public CallCard getDefaultCallCard() {
			//return the default call card in type CallCard.
			//*************************important*************************
			//if the key-value pair doesn't exist in shared preferences, return null.
			String defaultPin = settings.getString(Default_Pin, "");
			String pre = settings.getString(defaultPin+_PRE, "");
			
			CallCard result = null;
			if (defaultPin.length()>0 && pre.length()>0) {
				result = new CallCard(pre, defaultPin);
			}
			return result;
		}
	
		@SuppressLint("NewApi")
		public CallCard[] getAllCallCards() {
			//return a array of type CallCard (of fixed length CallCard_max),
			//**************************important************************
			//if the call card in shared preferences is less than CallCard_max,
			//fill the rest of array with null.
			Set<String> PinSet = settings.getStringSet(Pin_Set, new HashSet<String>());
			
			String[] PinArray = new String[CallCard_max];
			PinArray = (String[]) PinSet.toArray(PinArray);
			String[] preArray = new String[CallCard_max];
			
			int l = getCallCardnumber();
			for (int i=0; i<l ; i++) {
				preArray[i] = settings.getString(PinArray[i]+_PRE, "");
			}
			
			CallCard[] CardArray = new CallCard[CallCard_max];
			for (int i=0; i<l ; i++) {
				CardArray[i] = new CallCard(preArray[i], PinArray[i]);
			}
			
			return CardArray;	
		}
		
		@SuppressWarnings("deprecation")
		@SuppressLint("NewApi")
		public Contact[] getAllContacts() {
			//return a array of type Contact (of fixed length Contact_max),
			//**************************important************************
			//if the call card in shared preferences is less than Contact_max,
			//fill the rest of array with null.	
			Set<String> NameSet = settings.getStringSet(Name_Set, new HashSet<String>());

			String[] NameArray = new String[Contact_max];
			NameArray = (String[]) NameSet.toArray(NameArray);
			
			int l = getContactnumber();

			String[] PhoneArray = new String[Contact_max];
			int[] AlertArray = new int[Contact_max];
			Contact[] ContactArray = new Contact[Contact_max];
			int [] YearArray = new int[Contact_max], 
				   MonthArray = new int[Contact_max], 
				   DayArray = new int[Contact_max];
			
			Date record;
			
			for (int i=0; i<l; i++) {
				PhoneArray[i] = settings.getString(NameArray[i]+_PHONE, "");
				AlertArray[i] = (int) settings.getInt(NameArray[i]+_ALERT,0);
				
				YearArray[i] = settings.getInt(NameArray[i]+_YEAR,0);
				MonthArray[i] = settings.getInt(NameArray[i]+_MONTH, 0);
				DayArray[i] = settings.getInt(NameArray[i]+_DAY,0);
				record = new Date(YearArray[i],MonthArray[i],DayArray[i]);
				
				ContactArray[i] = new Contact(NameArray[i], PhoneArray[i],AlertArray[i],record);
			}
			return ContactArray;
		}

/*		these are the methods no longer used.	
 * 		@SuppressLint("NewApi")
		public void ChangeDefaultCallCard(CallCard a) {
			String Pin = a.getPin();
			remove("Default_Pin");
			putin("Default_Pin", Pin);		
		}
		
		@SuppressLint("NewApi")
		public void AddCallCard(CallCard a) {
			String Pin = a.getPin();
			String Pre = a.getPre();
			
			Set<String> PinSet = settings.getStringSet("Pin_Set", null);
			PinSet.add(Pin);
			
			remove("Pin_Set");
			putin("Pin_Set", PinSet);
			putin(Pin+"PRE", Pre);	
			
			int current = settings.getInt("Total_CallCard_Number", 0);
			current++;
			remove("Total_CallCard_Number");
			putin("Total_CallCard_Number",current);			
		} 
		
		@SuppressLint("NewApi")
		public void AddContact(Contact a) {
			Set<String> NameSet = settings.getStringSet("Name_Set", null);
			NameSet.add(a.getName());
			remove("Name_Set");
			putin("Name_Set",NameSet);
			
			int current = settings.getInt("Total_Contact_Number", 0);
			current++;
			remove("Total_Contact_Number");
			putin("Total_Contact_Number",current);
		}  */

		public void Clear() {
			//remove every key-value pair in shared preferences
			editor = settings.edit();
			editor.clear();
			editor.commit();
		}
	
		@SuppressWarnings("deprecation")
		public void StoreInfo() {
			//store the data in CallCard_total,CallCard_all,CallCard_inuse,Contact_all,Contact_total
			//into shared preferences.
			
			//add Pin_Set, pre, default_pin and total pin number;
			Set<String> tmp = new HashSet<String>();
		    for (int i=0; i<CallCard_total; i++) {
		    	tmp.add(CallCard_all[i].getPin());
		    	putin(CallCard_all[i].getPin()+SP._PRE,CallCard_all[i].getPre());
		    }
		    putin(SP.Pin_Set,tmp);
		    if (CallCard_inuse != null) { putin(SP.Default_Pin,CallCard_inuse.getPin());}
		    putin(SP.Total_CallCard_Number,CallCard_total);
		    //add Name_set, phone, total contact number;
		    tmp = new HashSet<String>();
		    for (int i=0; i<Contact_total; i++) {
		    	tmp.add(Contact_all[i].getName());
		    	putin(Contact_all[i].getName()+SP._PHONE,Contact_all[i].getPhone());
		    	putin(Contact_all[i].getName()+SP._ALERT,Contact_all[i].getAlertday());
		    	putin(Contact_all[i].getName()+SP._YEAR,Contact_all[i].getLastCall().getYear());
		    	putin(Contact_all[i].getName()+SP._MONTH,Contact_all[i].getLastCall().getMonth());
		    	putin(Contact_all[i].getName()+SP._DAY,Contact_all[i].getLastCall().getDay());
		    }
		    putin(SP.Name_Set,tmp);
		    putin(SP.Total_Contact_Number,Contact_total);    
		}
	}

	int CallCard_total = 0; // the number of call cards.
	public CallCard CallCard_inuse; //the default call card.
	CallCard[] CallCard_all; // the array of call card available.
	final int CallCard_max = 20; // the app can register at most 20 call cards.
	
	public class CallCard {
		String Pre, PIN;
		
		public CallCard (String Pre, String PIN){	
			this.Pre = Pre; 	//Pre is the prefix of the call card, say 18669138555,1,;
			this.PIN = PIN; 	
		}
		
		public String getPin(){	return PIN;		}
		
		public String getPre(){	return Pre;		}
		
		public void usethis(){
			CallCard_inuse = this;
		}
	}
	
	int Contact_total;  // the number of contact.
	Contact[] Contact_all; // the array of contact registered.
	final int Contact_max = 40; // the app can register at most 40 contacts.
	
	public class Contact {
		String Name, Phone;
		Button click;
		int alertday;
		Date lastcall;
		
		public Contact(String Name, String Phone, int alertday, Date last){
			/* This constructor is only used when the Contact is copied from shared
			 * preferences to the program.
			 */
			this.Name = Name;
			this.Phone = Phone;
			this.alertday = alertday;
			this.lastcall = last;
		}
		
		public Contact(String Name, String Phone, int alertday) {
			// This constructor is used when a new Contact is made
			this.Name = Name;
			this.Phone = Phone;
			this.alertday = alertday;
			this.lastcall = new Date();
		}
		
		public String getName(){ return Name;}
		
		public String getPhone(){ return Phone;}
		
		public int getAlertday() {return alertday;}
		
		public Date getLastCall() {return lastcall;}
		
		public void setLastCall(Date a) {lastcall = a;}
		
		public void present() {
			//create a button on the main layout.
			click = new Button(getApplicationContext());
			click.setText(Name);
			if ((alertday!=5) && ((now.getTime()-lastcall.getTime())/(1000*60*60*24)>alertday)) {
		//		click.setHintTextColor("indianred");
			}
			show.addView(click);
			click.setOnClickListener(new View.OnClickListener() {
				
				@Override
				public void onClick(View v) {
					if (CallCard_inuse != null )
						Dial();
				}
			}); 
		}
		
		public void Dial() {
			// call the guy and update the last call to the current date.
			String uri = "tel:"+CallCard_inuse.getPre()+","+CallCard_inuse.getPin()+","+Phone;
			Log.d("abc", uri);
			Intent calling = new Intent(Intent.ACTION_CALL,Uri.parse(uri));
			startActivity(calling);
			lastcall = new Date();
		}
	}
	
	public void SPtoV() {
		//transit every data from shared preferences to the variables in the program.
		CallCard_all = spmanager.getAllCallCards();
		CallCard_total = spmanager.getCallCardnumber();
		CallCard_inuse = spmanager.getDefaultCallCard();
		Contact_all = spmanager.getAllContacts();
		Contact_total = spmanager.getContactnumber();
	}	

}
